package com.qkl.xiatang.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qkl.xiatang.app.dto.BusinessDTO;
import com.qkl.xiatang.app.dto.sms.SmsSendResponse;
import com.qkl.xiatang.app.entity.sms.SmsDynamic;
import com.qkl.xiatang.app.entity.sms.SmsDynamicConfig;
import com.qkl.xiatang.app.entity.sms.SmsOutDTO;
import com.qkl.xiatang.app.mapper.SmsDynamicMapper;
import com.qkl.xiatang.app.utils.SmsSendUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

@Service
public class SmsDynamicService {

    @Autowired
    private SmsDynamicConfigService smsConfigService;

    @Autowired
    private SmsDynamicMapper smsMapper;

    /**
     * 查询最后发送动态码
     * @param phoneNum
     * @return
     */
    public SmsDynamic queryLastSms(String phoneNum){
        return  smsMapper.selectOne(new QueryWrapper<SmsDynamic>().eq("phone_num",phoneNum).orderByDesc("create_time").last("limit 1"));
    }

    /**
     * 添加短信动态码
     * @param smsDynamic
     * @return
     */
    public String addSms(SmsDynamic smsDynamic){
        if(null == smsDynamic.getCreateTime()){
            smsDynamic.setCreateTime(new Date());
        }
        smsMapper.insert(smsDynamic);
        return smsDynamic.getId();
    }

    /**
     * 根据id更新
     * @param smsDynamic
     */
    public void updateSmsById(SmsDynamic smsDynamic){
        smsMapper.updateById(smsDynamic);
    }

    public void updateSms(String id,Integer status,Integer verifyCount,String memo){
        SmsDynamic smsDynamic = new SmsDynamic();
        smsDynamic.setId(id);
        smsDynamic.setStatus(status);
        smsDynamic.setVerifyCount(verifyCount);
        smsDynamic.setMemo(memo);
        this.updateSmsById(smsDynamic);
    }


    /**
     * 发送短信动态码
     * @param phoneNum
     * @return
     */
    public BusinessDTO<SmsOutDTO> sendSms(String phoneNum) {
        return this.sendSms(null,phoneNum);
    }

    /**
     * 发送短信动态码
     * @param userId
     * @param phoneNum
     * @return
     */
    public BusinessDTO<SmsOutDTO> sendSms(String userId, String phoneNum) {
        SmsDynamicConfig smsConfig = smsConfigService.getConfig();
        if(null == smsConfig || smsConfig.configNotFinish()){
            return BusinessDTO.failBusiness("短信配置未完成");
        }
        int expireTime = smsConfig.getExpireTime();
        SmsDynamic sms = this.queryLastSms(phoneNum);
        if(!isCanSend(expireTime,sms)){
            return BusinessDTO.failBusiness("匆频繁发送动态码," + expireTime + " 秒后再发");
        }
        String code = SmsSendUtils.genVerifyCode();
        SmsSendResponse response = SmsSendUtils.sendPhoneCode(smsConfig,phoneNum,code);
        if(!response.success()){
            return BusinessDTO.failBusiness("手机短信动态码发送失败，" + response.getMessage());
        }

        SmsDynamic addSms = new SmsDynamic();
        addSms.setCode(code);
        addSms.setStatus(SmsSendUtils.STATUS_SEND);
        addSms.setPhoneNum(phoneNum);
        addSms.setVerifyTimes(smsConfig.getVerifyTimes());
        addSms.setUserId(userId);
        this.addSms(addSms);

        SmsOutDTO smsOutDTO = new SmsOutDTO();
        smsOutDTO.setExpireTime(expireTime);
        smsOutDTO.setVerifyTimes(smsConfig.getVerifyTimes());
        return BusinessDTO.sucessBusiness(smsOutDTO,"手机短信动态码发送成功");
    }

    /**
     * 验证短信动态码
     * @param phoneNum
     * @param code
     * @return
     */
    public BusinessDTO<SmsOutDTO> verifySms(String phoneNum, String code) {
        SmsDynamicConfig smsConfig = smsConfigService.getConfig();
        if(null == smsConfig || smsConfig.configNotFinish()){
            return BusinessDTO.failBusiness("短信配置未完成");
        }
        int expireTime = smsConfig.getExpireTime();
        SmsDynamic sms = this.queryLastSms(phoneNum);
        if(null == sms){
            return BusinessDTO.failBusiness("动态码未发送");
        }
        if(isExpire(expireTime,sms)){
            return BusinessDTO.failBusiness("动态码已过期");
        }
        if(SmsSendUtils.STATUS_OK.equals(sms.getStatus())){
            return BusinessDTO.failBusiness("动态码已验证通过，匆重复验证");
        }
        if(sms.getVerifyCount() > sms.getVerifyTimes()){
            return BusinessDTO.failBusiness("动态码验证次数超限");
        }
        String verifyCode = sms.getCode();
        Integer verifyCount = sms.getVerifyCount();
        String id = sms.getId();
        if(null == verifyCode || null == code || !verifyCode.equals(code)){
            this.updateSms(id,SmsSendUtils.STATUS_ERROR,++verifyCount,"动态码错误");
            return BusinessDTO.failBusiness("动态码错误");
        }
        this.updateSms(id,SmsSendUtils.STATUS_OK,++verifyCount,"动态码验证通过");
        return BusinessDTO.sucessBusiness("动态码验证通过");
    }


    /**
     * 动态码是否过期
     * @param expireTime
     * @param sms
     * @return
     */
    private static boolean isExpire(int expireTime,SmsDynamic sms){
        if(null == sms){
            return true;
        }
        return System.currentTimeMillis() > (expireTime * 1000 + sms.getCreateTime().getTime());
    }

    /**
     * 是否可以发送动态码
     * @param expireTime
     * @param sms
     * @return
     */
    private static boolean isCanSend(int expireTime,SmsDynamic sms){
        if(null == sms || SmsSendUtils.STATUS_OK.equals(sms.getStatus())){
            return true;
        }
        return System.currentTimeMillis() > (expireTime * 1000 + sms.getCreateTime().getTime());
    }

}
